home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QRZ! Ham Radio 8
/
QRZ Ham Radio Callsign Database - Volume 8.iso
/
mac
/
files
/
infodata
/
callbook.tar
/
callbook_1.3
/
hash.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-03-31
|
5KB
|
173 lines
/*
* Telnet callsign server sources copyright 1989 by Devon Bowen, KA2NRC.
* You may distribute and modify these files as you please as long as
* as long as credit to the original creator is given.
*
* This code is used to build the hash tables for the callsign server.
* Given a field number and an optional filename, it builds a two file
* hash table that allows quick reference by hash number for the field
* specified in the callsign file.
*
* The two files created by this program are callsign.X.data and
* callsign.X.search (where X is the field number the hash was done
* on). The search file is a list of constant length fields consisting
* of an unsigned int as the hash number and a file offset. Since the
* entries are constant lenghts, a binary search to find the hash
* number can be used. Once the entry is identified, the file offset
* is used to lseek into the data file. At this location in the data
* file will be a list of more file offsets terminated with a -1. The
* numbers here are offsets to all the lines in the original callsign
* file that hash to this hash number. These can then be looked at to
* see which values match the actual string.
*
* I know there are a few places this code can bomb, but since it's
* only intended to run once to build the tables, extensive error
* checking was not added. You may also have trouble with memory
* limits on your machine since this code *really* hogs memory. I
* don't really know how you might fix it if you run out of memory.
* The solution here was to generate the hash table on a machine
* that did have a sufficiently robust memory system. Then the hash
* tables were copied to the machine that was to run the server. Due
* to some endian problems some endian conversion programs had to be
* written to fix the tables as well. If you can't find a machine to
* generate the hash tables, get in touch with me and I'll see if I
* can get ours to you.
*/
#include <sys/file.h>
#include <stdio.h>
#include <ctype.h>
#define MAXPERHASH 10000
typedef struct link {
unsigned int offset;
struct link *next;
} LINK;
char *index(), *malloc();
unsigned short strhash();
LINK *last[65536], *count[65536]; /* helps stack to be global */
main(argc, argv)
int argc;
char **argv;
{
FILE *fd;
int fsearch, fdata;
char *prog = argv[0];
char buf[BUFSIZ], *search;
char searchfile[BUFSIZ], datafile[BUFSIZ];
unsigned short cur_hash=0;
int field, hash, temp;
int offsets[MAXPERHASH], bufcnt, cur_pos=0;
if (argc != 2 && argc != 3) {
fprintf(stderr, "usage: %s field [file]\n", prog);
exit(1);
} else
field = atoi(argv[1]);
if (argc == 3) {
fd = fopen(argv[2], "r");
if (fd == NULL) {
fprintf(stderr, "%s: %s no such file\n", prog, argv[2]);
exit(1);
}
} else
fd = stdin;
for (temp=0; temp<=65535; temp++) {
count[temp] = (LINK *) NULL;
last[temp] = (LINK *) NULL;
}
while (my_fgets(buf, BUFSIZ-1, fd)) {
for (temp=0, search=buf; temp < field; temp++)
if (!(search = index(search, '|'))) {
fprintf(stderr, "%s: bad field number\n", prog);
exit(1);
} else
search++;
if (*search == '|') {
cur_pos = ftell(fd);
continue;
}
hash = (int) strhash(search);
if (last[hash] == (LINK *) NULL)
count[hash] = last[hash] =
(LINK *) malloc(sizeof(LINK));
else
last[hash] = last[hash]->next =
(LINK *) malloc(sizeof(LINK));
if (last[hash] == (LINK *) NULL) {
fprintf(stderr, "%s: malloc failed\n", prog);
exit(1);
}
last[hash]->next = (LINK *) NULL;
last[hash]->offset = cur_pos;
cur_pos = ftell(fd);
}
fclose(fd);
sprintf(searchfile, "callsign.%d.search", field);
sprintf(datafile, "callsign.%d.data", field);
fsearch = open(searchfile, O_WRONLY | O_CREAT, 0644);
fdata = open(datafile, O_WRONLY | O_CREAT, 0644);
if (fsearch == -1 || fdata == -1) {
fprintf(stderr, "%s: error opening output file\n", prog);
exit(1);
}
cur_pos = cur_hash = 0;
do
if (count[cur_hash] != (LINK *) NULL) {
bufcnt = 0;
while (count[cur_hash] != (LINK *) NULL) {
offsets[bufcnt++] = count[cur_hash]->offset;
count[cur_hash] = count[cur_hash]->next;
}
offsets[bufcnt++] = -1;
if (write(fsearch,&cur_hash,sizeof(cur_hash))==-1) {
fprintf(stderr, "%s: write failed\n", prog);
exit(1);
}
if (write(fsearch,&cur_pos,sizeof(cur_pos))==-1) {
fprintf(stderr, "%s: write failed\n", prog);
exit(1);
}
if (write(fdata,offsets,bufcnt*sizeof(*offsets))==-1) {
fprintf(stderr, "%s: write failed\n", prog);
exit(1);
}
cur_pos += bufcnt * sizeof(*offsets);
}
while (cur_hash++ != 65535);
close(fsearch);
close(fdata);
}